import { isRealNum, valueIsError } from './validate'
import { isdatetime } from './datecontroll'
import { getcellvalue } from './getdata'
import numeral from 'numeral'

var SSF = {}
var make_ssf = function make_ssf(SSF) {
  SSF.version = '0.11.2'

  function _strrev(x) {
    var o = '',
      i = x.length - 1
    while (i >= 0) o += x.charAt(i--)
    return o
  }

  function fill(c, l) {
    var o = ''
    while (o.length < l) o += c
    return o
  }

  function pad0(v, d) {
    var t = '' + v
    return t.length >= d ? t : fill('0', d - t.length) + t
  }

  function pad_(v, d) {
    var t = '' + v
    return t.length >= d ? t : fill(' ', d - t.length) + t
  }

  function rpad_(v, d) {
    var t = '' + v
    return t.length >= d ? t : t + fill(' ', d - t.length)
  }

  function pad0r1(v, d) {
    var t = '' + Math.round(v)
    return t.length >= d ? t : fill('0', d - t.length) + t
  }

  function pad0r2(v, d) {
    var t = '' + v
    return t.length >= d ? t : fill('0', d - t.length) + t
  }
  var p2_32 = Math.pow(2, 32)

  function pad0r(v, d) {
    if (v > p2_32 || v < -p2_32) return pad0r1(v, d)
    var i = Math.round(v)
    return pad0r2(i, d)
  }

  function isgeneral(s, i) {
    i = i || 0
    return (
      s.length >= 7 + i &&
      (s.charCodeAt(i) | 32) === 103 &&
      (s.charCodeAt(i + 1) | 32) === 101 &&
      (s.charCodeAt(i + 2) | 32) === 110 &&
      (s.charCodeAt(i + 3) | 32) === 101 &&
      (s.charCodeAt(i + 4) | 32) === 114 &&
      (s.charCodeAt(i + 5) | 32) === 97 &&
      (s.charCodeAt(i + 6) | 32) === 108
    )
  }
  var days = [
    ['Sun', 'Sunday'],
    ['Mon', 'Monday'],
    ['Tue', 'Tuesday'],
    ['Wed', 'Wednesday'],
    ['Thu', 'Thursday'],
    ['Fri', 'Friday'],
    ['Sat', 'Saturday'],
  ]
  var months = [
    ['J', 'Jan', 'January'],
    ['F', 'Feb', 'February'],
    ['M', 'Mar', 'March'],
    ['A', 'Apr', 'April'],
    ['M', 'May', 'May'],
    ['J', 'Jun', 'June'],
    ['J', 'Jul', 'July'],
    ['A', 'Aug', 'August'],
    ['S', 'Sep', 'September'],
    ['O', 'Oct', 'October'],
    ['N', 'Nov', 'November'],
    ['D', 'Dec', 'December'],
  ]

  function init_table(t) {
    t[0] = 'General'
    t[1] = '0'
    t[2] = '0.00'
    t[3] = '#,##0'
    t[4] = '#,##0.00'
    t[9] = '0%'
    t[10] = '0.00%'
    t[11] = '0.00E+00'
    t[12] = '# ?/?'
    t[13] = '# ??/??'
    t[14] = 'm/d/yy'
    t[15] = 'd-mmm-yy'
    t[16] = 'd-mmm'
    t[17] = 'mmm-yy'
    t[18] = 'h:mm AM/PM'
    t[19] = 'h:mm:ss AM/PM'
    t[20] = 'h:mm'
    t[21] = 'h:mm:ss'
    t[22] = 'm/d/yy h:mm'
    t[37] = '#,##0 ;(#,##0)'
    t[38] = '#,##0 ;[Red](#,##0)'
    t[39] = '#,##0.00;(#,##0.00)'
    t[40] = '#,##0.00;[Red](#,##0.00)'
    t[45] = 'mm:ss'
    t[46] = '[h]:mm:ss'
    t[47] = 'mmss.0'
    t[48] = '##0.0E+0'
    t[49] = '@'
    t[56] = '"上午/下午 "hh"時"mm"分"ss"秒 "'
    t[65535] = 'General'
  }
  var table_fmt = {}
  init_table(table_fmt)
  /* Defaults determined by systematically testing in Excel 2019 */
  /* These formats appear to default to other formats in the table */
  var default_map = []
  var defi = 0
  //  5 -> 37 ...  8 -> 40
  for (defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi
  // 23 ->  0 ... 26 ->  0
  for (defi = 23; defi <= 26; ++defi) default_map[defi] = 0
  // 27 -> 14 ... 31 -> 14
  for (defi = 27; defi <= 31; ++defi) default_map[defi] = 14
  // 50 -> 14 ... 58 -> 14
  for (defi = 50; defi <= 58; ++defi) default_map[defi] = 14
  // 59 ->  1 ... 62 ->  4
  for (defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58
  // 67 ->  9 ... 68 -> 10
  for (defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58
  // 72 -> 14 ... 75 -> 17
  for (defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58
  // 69 -> 12 ... 71 -> 14
  for (defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57
  // 76 -> 20 ... 78 -> 22
  for (defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56
  // 79 -> 45 ... 81 -> 47
  for (defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34
  // 82 ->  0 ... 65536 -> 0 (omitted)
  /* These formats technically refer to Accounting formats with no equivalent */
  var default_str = []
  //  5 -- Currency,   0 decimal, black negative
  default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)'
  //  6 -- Currency,   0 decimal, red   negative
  default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)'
  //  7 -- Currency,   2 decimal, black negative
  default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)'
  //  8 -- Currency,   2 decimal, red   negative
  default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)'
  // 41 -- Accounting, 0 decimal, No Symbol
  default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)'
  // 42 -- Accounting, 0 decimal, $  Symbol
  default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)'
  // 43 -- Accounting, 2 decimal, No Symbol
  default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)'
  // 44 -- Accounting, 2 decimal, $  Symbol
  default_str[44] =
    '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)'

  function frac(x, D, mixed) {
    var sgn = x < 0 ? -1 : 1
    var B = x * sgn
    var P_2 = 0,
      P_1 = 1,
      P = 0
    var Q_2 = 1,
      Q_1 = 0,
      Q = 0
    var A = Math.floor(B)
    while (Q_1 < D) {
      A = Math.floor(B)
      P = A * P_1 + P_2
      Q = A * Q_1 + Q_2
      if (B - A < 0.00000005) break
      B = 1 / (B - A)
      P_2 = P_1
      P_1 = P
      Q_2 = Q_1
      Q_1 = Q
    }
    if (Q > D) {
      if (Q_1 > D) {
        Q = Q_2
        P = P_2
      } else {
        Q = Q_1
        P = P_1
      }
    }
    if (!mixed) return [0, sgn * P, Q]
    var q = Math.floor((sgn * P) / Q)
    return [q, sgn * P - q * Q, Q]
  }

  function parse_date_code(v, opts, b2) {
    if (v > 2958465 || v < 0) return null
    var date = v | 0,
      time = Math.floor(86400 * (v - date)),
      dow = 0
    var dout = []
    var out = {
      D: date,
      T: time,
      u: 86400 * (v - date) - time,
      y: 0,
      m: 0,
      d: 0,
      H: 0,
      M: 0,
      S: 0,
      q: 0,
    }
    if (Math.abs(out.u) < 1e-6) out.u = 0
    if (opts && opts.date1904) date += 1462
    if (out.u > 0.9999) {
      out.u = 0
      if (++time == 86400) {
        out.T = time = 0
        ++date
        ++out.D
      }
    }
    if (date === 60) {
      dout = b2 ? [1317, 10, 29] : [1900, 2, 29]
      dow = 3
    } else if (date === 0) {
      dout = b2 ? [1317, 8, 29] : [1900, 1, 0]
      dow = 6
    } else {
      if (date > 60) --date
      /* 1 = Jan 1 1900 in Gregorian */
      var d = new Date(1900, 0, 1)
      d.setDate(d.getDate() + date - 1)
      dout = [d.getFullYear(), d.getMonth() + 1, d.getDate()]
      dow = d.getDay()
      if (date < 60) dow = (dow + 6) % 7
      if (b2) dow = fix_hijri(d, dout)
    }
    out.y = dout[0]
    out.m = dout[1]
    out.d = dout[2]
    out.S = time % 60
    time = Math.floor(time / 60)
    out.M = time % 60
    time = Math.floor(time / 60)
    out.H = time
    out.q = dow
    return out
  }
  SSF.parse_date_code = parse_date_code
  var basedate = new Date(1899, 11, 31, 0, 0, 0)
  var dnthresh = basedate.getTime()
  var base1904 = new Date(1900, 2, 1, 0, 0, 0)

  function datenum_local(v, date1904) {
    var epoch = v.getTime()
    if (date1904) epoch -= 1461 * 24 * 60 * 60 * 1000
    else if (v >= base1904) epoch += 24 * 60 * 60 * 1000
    return (
      (epoch -
        (dnthresh +
          (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) /
      (24 * 60 * 60 * 1000)
    )
  }
  /* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
  function general_fmt_int(v) {
    return v.toString(10)
  }
  SSF._general_int = general_fmt_int
  /* ECMA-376 18.8.30 numFmt*/
  /* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
  var general_fmt_num = (function make_general_fmt_num() {
    var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/

    function strip_decimal(o) {
      return o.indexOf('.') == -1
        ? o
        : o.replace(trailing_zeroes_and_decimal, '$1')
    }
    /* General Exponential always shows 2 digits exp and trims the mantissa */
    var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/
    var exp_with_single_digit = /(E[+-])(\d)$/

    function normalize_exp(o) {
      if (o.indexOf('E') == -1) return o
      return o
        .replace(mantissa_zeroes_and_decimal, '$1E')
        .replace(exp_with_single_digit, '$10$2')
    }
    /* exponent >= -9 and <= 9 */
    function small_exp(v) {
      var w = v < 0 ? 12 : 11
      var o = strip_decimal(v.toFixed(12))
      if (o.length <= w) return o
      o = v.toPrecision(10)
      if (o.length <= w) return o
      return v.toExponential(5)
    }
    /* exponent >= 11 or <= -10 likely exponential */
    function large_exp(v) {
      var o = strip_decimal(v.toFixed(11))
      return o.length > (v < 0 ? 12 : 11) || o === '0' || o === '-0'
        ? v.toPrecision(6)
        : o
    }

    function general_fmt_num_base(v) {
      var V = Math.floor(Math.log(Math.abs(v)) * Math.LOG10E),
        o
      if (V >= -4 && V <= -1) o = v.toPrecision(10 + V)
      else if (Math.abs(V) <= 9) o = small_exp(v)
      else if (V === 10) o = v.toFixed(10).substr(0, 12)
      else o = large_exp(v)
      return strip_decimal(normalize_exp(o.toUpperCase()))
    }
    return general_fmt_num_base
  })()
  SSF._general_num = general_fmt_num
  /*
        "General" rules:
        - text is passed through ("@")
        - booleans are rendered as TRUE/FALSE
        - "up to 11 characters" displayed for numbers
        - Default date format (code 14) used for Dates
        TODO: technically the display depends on the width of the cell
    */
  function general_fmt(v, opts) {
    switch (typeof v) {
      case 'string':
        return v
      case 'boolean':
        return v ? 'TRUE' : 'FALSE'
      case 'number':
        return (v | 0) === v ? v.toString(10) : general_fmt_num(v)
      case 'undefined':
        return ''
      case 'object':
        if (v == null) return ''
        if (v instanceof Date)
          return format(14, datenum_local(v, opts && opts.date1904), opts)
    }
    throw new Error('unsupported value in General format: ' + v)
  }
  SSF._general = general_fmt

  function fix_hijri(date, o) {
    /* TODO: properly adjust y/m/d and  */
    o[0] -= 581
    var dow = date.getDay()
    if (date < 60) dow = (dow + 6) % 7
    return dow
  }
  var THAI_DIGITS = '\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59'.split(
    ''
  )
  /*jshint -W086 */
  function write_date(type, fmt, val, ss0) {
    var o = '',
      ss = 0,
      tt = 0,
      y = val.y,
      out,
      outl = 0
    switch (type) {
      case 98:
        /* 'b' buddhist year */ y = val.y + 543
      /* falls through */
      case 121:
        /* 'y' year */ switch (fmt.length) {
          case 1:
          case 2:
            out = y % 100
            outl = 2
            break
          default:
            out = y % 10000
            outl = 4
            break
        }
        break
      case 109:
        /* 'm' month */ switch (fmt.length) {
          case 1:
          case 2:
            out = val.m
            outl = fmt.length
            break
          case 3:
            return months[val.m - 1][1]
          case 5:
            return months[val.m - 1][0]
          default:
            return months[val.m - 1][2]
        }
        break
      case 100:
        /* 'd' day */ switch (fmt.length) {
          case 1:
          case 2:
            out = val.d
            outl = fmt.length
            break
          case 3:
            return days[val.q][0]
          default:
            return days[val.q][1]
        }
        break
      case 104:
        /* 'h' 12-hour */ switch (fmt.length) {
          case 1:
          case 2:
            out = 1 + ((val.H + 11) % 12)
            outl = fmt.length
            break
          default:
            throw 'bad hour format: ' + fmt
        }
        break
      case 72:
        /* 'H' 24-hour */ switch (fmt.length) {
          case 1:
          case 2:
            out = val.H
            outl = fmt.length
            break
          default:
            throw 'bad hour format: ' + fmt
        }
        break
      case 77:
        /* 'M' minutes */ switch (fmt.length) {
          case 1:
          case 2:
            out = val.M
            outl = fmt.length
            break
          default:
            throw 'bad minute format: ' + fmt
        }
        break
      case 115:
        /* 's' seconds */ if (
          fmt != 's' &&
          fmt != 'ss' &&
          fmt != '.0' &&
          fmt != '.00' &&
          fmt != '.000'
        )
          throw 'bad second format: ' + fmt
        if (val.u === 0 && (fmt == 's' || fmt == 'ss'))
          return pad0(val.S, fmt.length)
        if (ss0 >= 2) tt = ss0 === 3 ? 1000 : 100
        else tt = ss0 === 1 ? 10 : 1
        ss = Math.round(tt * (val.S + val.u))
        if (ss >= 60 * tt) ss = 0
        if (fmt === 's') return ss === 0 ? '0' : '' + ss / tt
        o = pad0(ss, 2 + ss0)
        if (fmt === 'ss') return o.substr(0, 2)
        return '.' + o.substr(2, fmt.length - 1)
      case 90:
        /* 'Z' absolute time */ switch (fmt) {
          case '[h]':
          case '[hh]':
            out = val.D * 24 + val.H
            break
          case '[m]':
          case '[mm]':
            out = (val.D * 24 + val.H) * 60 + val.M
            break
          case '[s]':
          case '[ss]':
            out =
              ((val.D * 24 + val.H) * 60 + val.M) * 60 +
              Math.round(val.S + val.u)
            break
          default:
            throw 'bad abstime format: ' + fmt
        }
        outl = fmt.length === 3 ? 1 : 2
        break
      case 101:
        /* 'e' era */ out = y
        outl = 1
        break
    }
    var outstr = outl > 0 ? pad0(out, outl) : ''
    return outstr
  }
  /*jshint +W086 */
  function commaify(s) {
    var w = 3
    if (s.length <= w) return s
    var j = s.length % w,
      o = s.substr(0, j)
    for (; j != s.length; j += w)
      o += (o.length > 0 ? ',' : '') + s.substr(j, w)
    return o
  }
  var write_num = (function make_write_num() {
    var pct1 = /%/g

    function write_num_pct(type, fmt, val) {
      var sfmt = fmt.replace(pct1, ''),
        mul = fmt.length - sfmt.length
      return write_num(type, sfmt, val * Math.pow(10, 2 * mul)) + fill('%', mul)
    }

    function write_num_cm(type, fmt, val) {
      var idx = fmt.length - 1
      while (fmt.charCodeAt(idx - 1) === 44) --idx
      return write_num(
        type,
        fmt.substr(0, idx),
        val / Math.pow(10, 3 * (fmt.length - idx))
      )
    }

    function write_num_exp(fmt, val) {
      var o
      var idx = fmt.indexOf('E') - fmt.indexOf('.') - 1
      if (fmt.match(/^#+0.0E\+0$/)) {
        if (val == 0) return '0.0E+0'
        else if (val < 0) return '-' + write_num_exp(fmt, -val)
        var period = fmt.indexOf('.')
        if (period === -1) period = fmt.indexOf('E')
        var ee = Math.floor(Math.log(val) * Math.LOG10E) % period
        if (ee < 0) ee += period
        o = (val / Math.pow(10, ee)).toPrecision(
          idx + 1 + ((period + ee) % period)
        )
        if (o.indexOf('e') === -1) {
          var fakee = Math.floor(Math.log(val) * Math.LOG10E)
          if (o.indexOf('.') === -1)
            o = o.charAt(0) + '.' + o.substr(1) + 'E+' + (fakee - o.length + ee)
          else o += 'E+' + (fakee - ee)
          while (o.substr(0, 2) === '0.') {
            o = o.charAt(0) + o.substr(2, period) + '.' + o.substr(2 + period)
            o = o.replace(/^0+([1-9])/, '$1').replace(/^0+\./, '0.')
          }
          o = o.replace(/\+-/, '-')
        }
        o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/, function($$, $1, $2, $3) {
          return (
            $1 +
            $2 +
            $3.substr(0, (period + ee) % period) +
            '.' +
            $3.substr(ee) +
            'E'
          )
        })
      } else o = val.toExponential(idx)
      if (fmt.match(/E\+00$/) && o.match(/e[+-]\d$/))
        o = o.substr(0, o.length - 1) + '0' + o.charAt(o.length - 1)
      if (fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/, 'e')
      return o.replace('e', 'E')
    }
    var frac1 = /# (\?+)( ?)\/( ?)(\d+)/

    function write_num_f1(r, aval, sign) {
      var den = parseInt(r[4], 10),
        rr = Math.round(aval * den),
        base = Math.floor(rr / den)
      var myn = rr - base * den,
        myd = den
      return (
        sign +
        (base === 0 ? '' : '' + base) +
        ' ' +
        (myn === 0
          ? fill(' ', r[1].length + 1 + r[4].length)
          : pad_(myn, r[1].length) + r[2] + '/' + r[3] + pad0(myd, r[4].length))
      )
    }

    function write_num_f2(r, aval, sign) {
      return (
        sign +
        (aval === 0 ? '' : '' + aval) +
        fill(' ', r[1].length + 2 + r[4].length)
      )
    }
    var dec1 = /^#*0*\.([0#]+)/
    var closeparen = /\).*[0#]/
    var phone = /\(###\) ###\\?-####/

    function hashq(str) {
      var o = '',
        cc
      for (var i = 0; i != str.length; ++i)
        switch ((cc = str.charCodeAt(i))) {
          case 35:
            break
          case 63:
            o += ' '
            break
          case 48:
            o += '0'
            break
          default:
            o += String.fromCharCode(cc)
        }
      return o
    }

    function rnd(val, d) {
      var dd = Math.pow(10, d)
      return '' + Math.round(val * dd) / dd
    }

    function dec(val, d) {
      var _frac = val - Math.floor(val),
        dd = Math.pow(10, d)
      if (d < ('' + Math.round(_frac * dd)).length) return 0
      return Math.round(_frac * dd)
    }

    function carry(val, d) {
      if (
        d < ('' + Math.round((val - Math.floor(val)) * Math.pow(10, d))).length
      ) {
        return 1
      }
      return 0
    }

    function flr(val) {
      if (val < 2147483647 && val > -2147483648)
        return '' + (val >= 0 ? val | 0 : (val - 1) | 0)
      return '' + Math.floor(val)
    }

    function write_num_flt(type, fmt, val) {
      if (type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
        var ffmt = fmt
          .replace(/\( */, '')
          .replace(/ \)/, '')
          .replace(/\)/, '')
        if (val >= 0) return write_num_flt('n', ffmt, val)
        return '(' + write_num_flt('n', ffmt, -val) + ')'
      }
      if (fmt.charCodeAt(fmt.length - 1) === 44)
        return write_num_cm(type, fmt, val)
      if (fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val)
      if (fmt.indexOf('E') !== -1) return write_num_exp(fmt, val)
      if (fmt.charCodeAt(0) === 36)
        return (
          '$' +
          write_num_flt(type, fmt.substr(fmt.charAt(1) == ' ' ? 2 : 1), val)
        )
      var o
      var r,
        ri,
        ff,
        aval = Math.abs(val),
        sign = val < 0 ? '-' : ''
      if (fmt.match(/^00+$/)) return sign + pad0r(aval, fmt.length)
      if (fmt.match(/^[#?]+$/)) {
        o = pad0r(val, 0)
        if (o === '0') o = ''
        return o.length > fmt.length
          ? o
          : hashq(fmt.substr(0, fmt.length - o.length)) + o
      }
      if ((r = fmt.match(frac1))) return write_num_f1(r, aval, sign)
      if (fmt.match(/^#+0+$/))
        return sign + pad0r(aval, fmt.length - fmt.indexOf('0'))
      if ((r = fmt.match(dec1))) {
        o = rnd(val, r[1].length)
          .replace(/^([^\.]+)$/, '$1.' + hashq(r[1]))
          .replace(/\.$/, '.' + hashq(r[1]))
          .replace(/\.(\d*)$/, function($$, $1) {
            return '.' + $1 + fill('0', hashq(r[1]).length - $1.length)
          })
        return fmt.indexOf('0.') !== -1 ? o : o.replace(/^0\./, '.')
      }
      fmt = fmt.replace(/^#+([0.])/, '$1')
      if ((r = fmt.match(/^(0*)\.(#*)$/))) {
        return (
          sign +
          rnd(aval, r[2].length)
            .replace(/\.(\d*[1-9])0*$/, '.$1')
            .replace(/^(-?\d*)$/, '$1.')
            .replace(/^0\./, r[1].length ? '0.' : '.')
        )
      }
      if ((r = fmt.match(/^#{1,3},##0(\.?)$/)))
        return sign + commaify(pad0r(aval, 0))
      if ((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
        return val < 0
          ? '-' + write_num_flt(type, fmt, -val)
          : commaify('' + (Math.floor(val) + carry(val, r[1].length))) +
              '.' +
              pad0(dec(val, r[1].length), r[1].length)
      }
      if ((r = fmt.match(/^#,#*,#0/)))
        return write_num_flt(type, fmt.replace(/^#,#*,/, ''), val)
      if ((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
        o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g, ''), val))
        ri = 0
        return _strrev(
          _strrev(fmt.replace(/\\/g, '')).replace(/[0#]/g, function(x) {
            return ri < o.length ? o.charAt(ri++) : x === '0' ? '0' : ''
          })
        )
      }
      if (fmt.match(phone)) {
        o = write_num_flt(type, '##########', val)
        return '(' + o.substr(0, 3) + ') ' + o.substr(3, 3) + '-' + o.substr(6)
      }
      var oa = ''
      if ((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
        ri = Math.min(r[4].length, 7)
        ff = frac(aval, Math.pow(10, ri) - 1, false)
        o = '' + sign
        oa = write_num('n', r[1], ff[1])
        if (oa.charAt(oa.length - 1) == ' ')
          oa = oa.substr(0, oa.length - 1) + '0'
        o += oa + r[2] + '/' + r[3]
        oa = rpad_(ff[2], ri)
        if (oa.length < r[4].length)
          oa = hashq(r[4].substr(r[4].length - oa.length)) + oa
        o += oa
        return o
      }
      if ((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
        ri = Math.min(Math.max(r[1].length, r[4].length), 7)
        ff = frac(aval, Math.pow(10, ri) - 1, true)
        return (
          sign +
          (ff[0] || (ff[1] ? '' : '0')) +
          ' ' +
          (ff[1]
            ? pad_(ff[1], ri) + r[2] + '/' + r[3] + rpad_(ff[2], ri)
            : fill(' ', 2 * ri + 1 + r[2].length + r[3].length))
        )
      }
      if ((r = fmt.match(/^[#0?]+$/))) {
        o = pad0r(val, 0)
        if (fmt.length <= o.length) return o
        return hashq(fmt.substr(0, fmt.length - o.length)) + o
      }
      if ((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
        o =
          '' + val.toFixed(Math.min(r[2].length, 10)).replace(/([^0])0+$/, '$1')
        ri = o.indexOf('.')
        var lres = fmt.indexOf('.') - ri,
          rres = fmt.length - o.length - lres
        return hashq(fmt.substr(0, lres) + o + fmt.substr(fmt.length - rres))
      }
      if ((r = fmt.match(/^00,000\.([#0]*0)$/))) {
        ri = dec(val, r[1].length)
        return val < 0
          ? '-' + write_num_flt(type, fmt, -val)
          : commaify(flr(val))
              .replace(/^\d,\d{3}$/, '0$&')
              .replace(/^\d*$/, function($$) {
                return (
                  '00,' + ($$.length < 3 ? pad0(0, 3 - $$.length) : '') + $$
                )
              }) +
              '.' +
              pad0(ri, r[1].length)
      }
      switch (fmt) {
        case '###,##0.00':
          return write_num_flt(type, '#,##0.00', val)
        case '###,###':
        case '##,###':
        case '#,###':
          var x = commaify(pad0r(aval, 0))
          return x !== '0' ? sign + x : ''
        case '###,###.00':
          return write_num_flt(type, '###,##0.00', val).replace(/^0\./, '.')
        case '#,###.00':
          return write_num_flt(type, '#,##0.00', val).replace(/^0\./, '.')
        default:
      }
      throw new Error('unsupported format |' + fmt + '|')
    }

    function write_num_cm2(type, fmt, val) {
      var idx = fmt.length - 1
      while (fmt.charCodeAt(idx - 1) === 44) --idx
      return write_num(
        type,
        fmt.substr(0, idx),
        val / Math.pow(10, 3 * (fmt.length - idx))
      )
    }

    function write_num_pct2(type, fmt, val) {
      var sfmt = fmt.replace(pct1, ''),
        mul = fmt.length - sfmt.length
      return write_num(type, sfmt, val * Math.pow(10, 2 * mul)) + fill('%', mul)
    }

    function write_num_exp2(fmt, val) {
      var o
      var idx = fmt.indexOf('E') - fmt.indexOf('.') - 1
      if (fmt.match(/^#+0.0E\+0$/)) {
        if (val == 0) return '0.0E+0'
        else if (val < 0) return '-' + write_num_exp2(fmt, -val)
        var period = fmt.indexOf('.')
        if (period === -1) period = fmt.indexOf('E')
        var ee = Math.floor(Math.log(val) * Math.LOG10E) % period
        if (ee < 0) ee += period
        o = (val / Math.pow(10, ee)).toPrecision(
          idx + 1 + ((period + ee) % period)
        )
        if (!o.match(/[Ee]/)) {
          var fakee = Math.floor(Math.log(val) * Math.LOG10E)
          if (o.indexOf('.') === -1)
            o = o.charAt(0) + '.' + o.substr(1) + 'E+' + (fakee - o.length + ee)
          else o += 'E+' + (fakee - ee)
          o = o.replace(/\+-/, '-')
        }
        o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/, function($$, $1, $2, $3) {
          return (
            $1 +
            $2 +
            $3.substr(0, (period + ee) % period) +
            '.' +
            $3.substr(ee) +
            'E'
          )
        })
      } else o = val.toExponential(idx)
      if (fmt.match(/E\+00$/) && o.match(/e[+-]\d$/))
        o = o.substr(0, o.length - 1) + '0' + o.charAt(o.length - 1)
      if (fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/, 'e')
      return o.replace('e', 'E')
    }

    function write_num_int(type, fmt, val) {
      if (type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
        var ffmt = fmt
          .replace(/\( */, '')
          .replace(/ \)/, '')
          .replace(/\)/, '')
        if (val >= 0) return write_num_int('n', ffmt, val)
        return '(' + write_num_int('n', ffmt, -val) + ')'
      }
      if (fmt.charCodeAt(fmt.length - 1) === 44)
        return write_num_cm2(type, fmt, val)
      if (fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val)
      if (fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val)
      if (fmt.charCodeAt(0) === 36)
        return (
          '$' +
          write_num_int(type, fmt.substr(fmt.charAt(1) == ' ' ? 2 : 1), val)
        )
      var o
      var r,
        ri,
        ff,
        aval = Math.abs(val),
        sign = val < 0 ? '-' : ''
      if (fmt.match(/^00+$/)) return sign + pad0(aval, fmt.length)
      if (fmt.match(/^[#?]+$/)) {
        o = '' + val
        if (val === 0) o = ''
        return o.length > fmt.length
          ? o
          : hashq(fmt.substr(0, fmt.length - o.length)) + o
      }
      if ((r = fmt.match(frac1))) return write_num_f2(r, aval, sign)
      if (fmt.match(/^#+0+$/))
        return sign + pad0(aval, fmt.length - fmt.indexOf('0'))
      if ((r = fmt.match(dec1))) {
        o = ('' + val)
          .replace(/^([^\.]+)$/, '$1.' + hashq(r[1]))
          .replace(/\.$/, '.' + hashq(r[1]))
        o = o.replace(/\.(\d*)$/, function($$, $1) {
          return '.' + $1 + fill('0', hashq(r[1]).length - $1.length)
        })
        return fmt.indexOf('0.') !== -1 ? o : o.replace(/^0\./, '.')
      }
      fmt = fmt.replace(/^#+([0.])/, '$1')
      if ((r = fmt.match(/^(0*)\.(#*)$/))) {
        return (
          sign +
          ('' + aval)
            .replace(/\.(\d*[1-9])0*$/, '.$1')
            .replace(/^(-?\d*)$/, '$1.')
            .replace(/^0\./, r[1].length ? '0.' : '.')
        )
      }
      if ((r = fmt.match(/^#{1,3},##0(\.?)$/)))
        return sign + commaify('' + aval)
      if ((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
        return val < 0
          ? '-' + write_num_int(type, fmt, -val)
          : commaify('' + val) + '.' + fill('0', r[1].length)
      }
      if ((r = fmt.match(/^#,#*,#0/)))
        return write_num_int(type, fmt.replace(/^#,#*,/, ''), val)
      if ((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
        o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g, ''), val))
        ri = 0
        return _strrev(
          _strrev(fmt.replace(/\\/g, '')).replace(/[0#]/g, function(x) {
            return ri < o.length ? o.charAt(ri++) : x === '0' ? '0' : ''
          })
        )
      }
      if (fmt.match(phone)) {
        o = write_num_int(type, '##########', val)
        return '(' + o.substr(0, 3) + ') ' + o.substr(3, 3) + '-' + o.substr(6)
      }
      var oa = ''
      if ((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
        ri = Math.min(r[4].length, 7)
        ff = frac(aval, Math.pow(10, ri) - 1, false)
        o = '' + sign
        oa = write_num('n', r[1], ff[1])
        if (oa.charAt(oa.length - 1) == ' ')
          oa = oa.substr(0, oa.length - 1) + '0'
        o += oa + r[2] + '/' + r[3]
        oa = rpad_(ff[2], ri)
        if (oa.length < r[4].length)
          oa = hashq(r[4].substr(r[4].length - oa.length)) + oa
        o += oa
        return o
      }
      if ((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
        ri = Math.min(Math.max(r[1].length, r[4].length), 7)
        ff = frac(aval, Math.pow(10, ri) - 1, true)
        return (
          sign +
          (ff[0] || (ff[1] ? '' : '0')) +
          ' ' +
          (ff[1]
            ? pad_(ff[1], ri) + r[2] + '/' + r[3] + rpad_(ff[2], ri)
            : fill(' ', 2 * ri + 1 + r[2].length + r[3].length))
        )
      }
      if ((r = fmt.match(/^[#0?]+$/))) {
        o = '' + val
        if (fmt.length <= o.length) return o
        return hashq(fmt.substr(0, fmt.length - o.length)) + o
      }
      if ((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
        o =
          '' + val.toFixed(Math.min(r[2].length, 10)).replace(/([^0])0+$/, '$1')
        ri = o.indexOf('.')
        var lres = fmt.indexOf('.') - ri,
          rres = fmt.length - o.length - lres
        return hashq(fmt.substr(0, lres) + o + fmt.substr(fmt.length - rres))
      }
      if ((r = fmt.match(/^00,000\.([#0]*0)$/))) {
        return val < 0
          ? '-' + write_num_int(type, fmt, -val)
          : commaify('' + val)
              .replace(/^\d,\d{3}$/, '0$&')
              .replace(/^\d*$/, function($$) {
                return (
                  '00,' + ($$.length < 3 ? pad0(0, 3 - $$.length) : '') + $$
                )
              }) +
              '.' +
              pad0(0, r[1].length)
      }
      switch (fmt) {
        case '###,###':
        case '##,###':
        case '#,###':
          var x = commaify('' + aval)
          return x !== '0' ? sign + x : ''
        default:
          if (fmt.match(/\.[0#?]*$/))
            return (
              write_num_int(type, fmt.slice(0, fmt.lastIndexOf('.')), val) +
              hashq(fmt.slice(fmt.lastIndexOf('.')))
            )
      }
      throw new Error('unsupported format |' + fmt + '|')
    }
    return function write_num(type, fmt, val) {
      return (val | 0) === val
        ? write_num_int(type, fmt, val)
        : write_num_flt(type, fmt, val)
    }
  })()

  function split_fmt(fmt) {
    var out = []
    var in_str = false /*, cc*/
    for (var i = 0, j = 0; i < fmt.length; ++i)
      switch (/*cc=*/ fmt.charCodeAt(i)) {
        case 34:
          /* '"' */ in_str = !in_str
          break
        case 95:
        case 42:
        case 92:
          /* '_' '*' '\\' */
          ++i
          break
        case 59:
          /* ';' */ out[out.length] = fmt.substr(j, i - j)
          j = i + 1
      }
    out[out.length] = fmt.substr(j)
    if (in_str === true)
      throw new Error('Format |' + fmt + '| unterminated string ')
    return out
  }
  SSF._split = split_fmt
  var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/

  function fmt_is_date(fmt) {
    var i = 0,
      /*cc = 0,*/ c = '',
      o = ''
    while (i < fmt.length) {
      switch ((c = fmt.charAt(i))) {
        case 'G':
          if (isgeneral(fmt, i)) i += 6
          i++
          break
        case '"':
          for (; /*cc=*/ fmt.charCodeAt(++i) !== 34 && i < fmt.length; ) {
            /*empty*/
          }
          ++i
          break
        case '\\':
          i += 2
          break
        case '_':
          i += 2
          break
        case '@':
          ++i
          break
        case 'B':
        case 'b':
          if (fmt.charAt(i + 1) === '1' || fmt.charAt(i + 1) === '2')
            return true
        /* falls through */
        case 'M':
        case 'D':
        case 'Y':
        case 'H':
        case 'S':
        case 'E':
        /* falls through */
        case 'm':
        case 'd':
        case 'y':
        case 'h':
        case 's':
        case 'e':
        case 'g':
          return true
        case 'A':
        case 'a':
        case '上':
          if (fmt.substr(i, 3).toUpperCase() === 'A/P') return true
          if (fmt.substr(i, 5).toUpperCase() === 'AM/PM') return true
          if (fmt.substr(i, 5).toUpperCase() === '上午/下午') return true
          ++i
          break
        case '[':
          o = c
          while (fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i)
          if (o.match(abstime)) return true
          break
        case '.':
        /* falls through */
        case '0':
        case '#':
          while (
            i < fmt.length &&
            ('0#?.,E+-%'.indexOf((c = fmt.charAt(++i))) > -1 ||
              (c == '\\' &&
                fmt.charAt(i + 1) == '-' &&
                '0#'.indexOf(fmt.charAt(i + 2)) > -1))
          ) {
            /* empty */
          }
          break
        case '?':
          while (fmt.charAt(++i) === c) {
            /* empty */
          }
          break
        case '*':
          ++i
          if (fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i
          break
        case '(':
        case ')':
          ++i
          break
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
          while (i < fmt.length && '0123456789'.indexOf(fmt.charAt(++i)) > -1) {
            /* empty */
          }
          break
        case ' ':
          ++i
          break
        default:
          ++i
          break
      }
    }
    return false
  }
  SSF.is_date = fmt_is_date

  function eval_fmt(fmt, v, opts, flen) {
    var out = [],
      o = '',
      i = 0,
      c = '',
      lst = 't',
      dt,
      j,
      cc
    var hr = 'H'
    /* Tokenize */
    while (i < fmt.length) {
      switch ((c = fmt.charAt(i))) {
        case 'G':
          /* General */ if (!isgeneral(fmt, i))
            throw new Error('unrecognized character ' + c + ' in ' + fmt)
          out[out.length] = {
            t: 'G',
            v: 'General',
          }
          i += 7
          break
        case '"':
          /* Literal text */ for (
            o = '';
            (cc = fmt.charCodeAt(++i)) !== 34 && i < fmt.length;

          )
            o += String.fromCharCode(cc)
          out[out.length] = {
            t: 't',
            v: o,
          }
          ++i
          break
        case '\\':
          var w = fmt.charAt(++i),
            t = w === '(' || w === ')' ? w : 't'
          out[out.length] = {
            t: t,
            v: w,
          }
          ++i
          break
        case '_':
          out[out.length] = {
            t: 't',
            v: ' ',
          }
          i += 2
          break
        case '@':
          /* Text Placeholder */ out[out.length] = {
            t: 'T',
            v: v,
          }
          ++i
          break
        case 'B':
        case 'b':
          if (fmt.charAt(i + 1) === '1' || fmt.charAt(i + 1) === '2') {
            if (dt == null) {
              dt = parse_date_code(v, opts, fmt.charAt(i + 1) === '2')
              if (dt == null) return ''
            }
            out[out.length] = {
              t: 'X',
              v: fmt.substr(i, 2),
            }
            lst = c
            i += 2
            break
          }
        /* falls through */
        case 'M':
        case 'D':
        case 'Y':
        case 'H':
        case 'S':
        case 'E':
          c = c.toLowerCase()
        /* falls through */
        case 'm':
        case 'd':
        case 'y':
        case 'h':
        case 's':
        case 'e':
        case 'g':
          if (v < 0) return ''
          if (dt == null) {
            dt = parse_date_code(v, opts)
            if (dt == null) return '#####'
          }
          o = c
          while (++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o += c
          if (c === 'm' && lst.toLowerCase() === 'h') c = 'M'
          if (c === 'h') c = hr
          out[out.length] = {
            t: c,
            v: o,
          }
          lst = c
          break
        case 'A':
        case 'a':
        case '上':
          var q = {
            t: c,
            v: c,
          }
          if (dt == null) dt = parse_date_code(v, opts)
          if (fmt.substr(i, 3).toUpperCase() === 'A/P') {
            if (dt != null) q.v = dt.H >= 12 ? 'P' : 'A'
            q.t = 'T'
            hr = 'h'
            i += 3
          } else if (fmt.substr(i, 5).toUpperCase() === 'AM/PM') {
            if (dt != null) q.v = dt.H >= 12 ? 'PM' : 'AM'
            q.t = 'T'
            i += 5
            hr = 'h'
          } else if (fmt.substr(i, 5).toUpperCase() === '上午/下午') {
            if (dt != null) q.v = dt.H >= 12 ? '下午' : '上午'
            q.t = 'T'
            i += 5
            hr = 'h'
          } else {
            q.t = 't'
            ++i
          }
          if (dt == null && q.t === 'T') return ''
          out[out.length] = q
          lst = c
          break
        case '[':
          o = c
          while (fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i)
          if (o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|'
          if (o.match(abstime)) {
            if (dt == null) {
              dt = parse_date_code(v, opts)
              if (dt == null) return ''
            }
            out[out.length] = {
              t: 'Z',
              v: o.toLowerCase(),
            }
            lst = o.charAt(1)
          } else if (o.indexOf('$') > -1) {
            o = (o.match(/\$([^-\[\]]*)/) || [])[1] || '$'
            if (!fmt_is_date(fmt))
              out[out.length] = {
                t: 't',
                v: o,
              }
          }
          break
        /* Numbers */
        case '.':
          if (dt != null) {
            o = c
            while (++i < fmt.length && (c = fmt.charAt(i)) === '0') o += c
            out[out.length] = {
              t: 's',
              v: o,
            }
            break
          }
        /* falls through */
        case '0':
        case '#':
          o = c
          while (
            ++i < fmt.length &&
            '0#?.,E+-%'.indexOf((c = fmt.charAt(i))) > -1
          )
            o += c
          out[out.length] = {
            t: 'n',
            v: o,
          }
          break
        case '?':
          o = c
          while (fmt.charAt(++i) === c) o += c
          out[out.length] = {
            t: c,
            v: o,
          }
          lst = c
          break
        case '*':
          ++i
          if (fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i
          break // **
        case '(':
        case ')':
          out[out.length] = {
            t: flen === 1 ? 't' : c,
            v: c,
          }
          ++i
          break
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
          o = c
          while (i < fmt.length && '0123456789'.indexOf(fmt.charAt(++i)) > -1)
            o += fmt.charAt(i)
          out[out.length] = {
            t: 'D',
            v: o,
          }
          break
        case ' ':
          out[out.length] = {
            t: c,
            v: c,
          }
          ++i
          break
        case '$':
          out[out.length] = {
            t: 't',
            v: '$',
          }
          ++i
          break
        default:
          // if ("¤฿BsBr₵₡₫ƒFtRs.₭kr£₤Lm₥₦₱PQRSkRp৲৳R$S/.〒₮₩¥NT￥zł₴₪៛руб€＄,$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
          if (
            "¤฿BsBr₵₡₫ƒFtRs.₭kr£₤Lm₥₦₱PQRSkRp৲৳R$S/.〒₮₩¥NT￥zł₴₪៛руб€＄,$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP$￥LekdinAf$dhAflRial?￡BirrKzMOPPGKRsGsB/R$ррlevkrKMzBsPNuFBuKPkrRD$NfkCFA?CVEGMDFrCDHTGNAfLFdjKGSFGGHSRielKCFknKshLSLL￡LtRFRONArRfMWKRMMURsMROS/KMDLMTnRC$kr€GELCHFSLLSCRDbSZLSDGSOSSomFCFPTShT$VUVQUGXгрнsomWSTNT$FtDramRpZMWFCFA".indexOf(
              c
            ) === -1
          )
            throw new Error('unrecognized character ' + c + ' in ' + fmt)
          out[out.length] = {
            t: 't',
            v: c,
          }
          ++i
          break
      }
    }
    /* Scan for date/time parts */
    var bt = 0,
      ss0 = 0,
      ssm
    for (i = out.length - 1, lst = 't'; i >= 0; --i) {
      switch (out[i].t) {
        case 'h':
        case 'H':
          out[i].t = hr
          lst = 'h'
          if (bt < 1) bt = 1
          break
        case 's':
          if ((ssm = out[i].v.match(/\.0+$/)))
            ss0 = Math.max(ss0, ssm[0].length - 1)
          if (bt < 3) bt = 3
        /* falls through */
        case 'd':
        case 'y':
        case 'M':
        case 'e':
          lst = out[i].t
          break
        case 'm':
          if (lst === 's') {
            out[i].t = 'M'
            if (bt < 2) bt = 2
          }
          break
        case 'X':
          /*if(out[i].v === "B2");*/ break
        case 'Z':
          if (bt < 1 && out[i].v.match(/[Hh]/)) bt = 1
          if (bt < 2 && out[i].v.match(/[Mm]/)) bt = 2
          if (bt < 3 && out[i].v.match(/[Ss]/)) bt = 3
      }
    }
    /* time rounding depends on presence of minute / second / usec fields */
    switch (bt) {
      case 0:
        break
      case 1:
        if (dt.u >= 0.5) {
          dt.u = 0
          ++dt.S
        }
        if (dt.S >= 60) {
          dt.S = 0
          ++dt.M
        }
        if (dt.M >= 60) {
          dt.M = 0
          ++dt.H
        }
        break
      case 2:
        if (dt.u >= 0.5) {
          dt.u = 0
          ++dt.S
        }
        if (dt.S >= 60) {
          dt.S = 0
          ++dt.M
        }
        break
    }
    /* replace fields */
    var nstr = '',
      jj
    for (i = 0; i < out.length; ++i) {
      switch (out[i].t) {
        case 't':
        case 'T':
        case ' ':
        case 'D':
          break
        case 'X':
          out[i].v = ''
          out[i].t = ';'
          break
        case 'd':
        case 'm':
        case 'y':
        case 'h':
        case 'H':
        case 'M':
        case 's':
        case 'e':
        case 'b':
        case 'Z':
          out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0)
          out[i].t = 't'
          break
        case 'n':
        case '?':
          jj = i + 1
          while (
            out[jj] != null &&
            ((c = out[jj].t) === '?' ||
              c === 'D' ||
              ((c === ' ' || c === 't') &&
                out[jj + 1] != null &&
                (out[jj + 1].t === '?' ||
                  (out[jj + 1].t === 't' && out[jj + 1].v === '/'))) ||
              (out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
              (c === 't' &&
                (out[jj].v === '/' ||
                  (out[jj].v === ' ' &&
                    out[jj + 1] != null &&
                    out[jj + 1].t == '?'))))
          ) {
            out[i].v += out[jj].v
            out[jj] = {
              v: '',
              t: ';',
            }
            ++jj
          }
          nstr += out[i].v
          i = jj - 1
          break
        case 'G':
          out[i].t = 't'
          out[i].v = general_fmt(v, opts)
          break
      }
    }
    var vv = '',
      myv,
      ostr
    if (nstr.length > 0) {
      if (nstr.charCodeAt(0) == 40) {
        /* '(' */ myv = v < 0 && nstr.charCodeAt(0) === 45 ? -v : v
        ostr = write_num('n', nstr, myv)
      } else {
        myv = v < 0 && flen > 1 ? -v : v
        ostr = write_num('n', nstr, myv)
        if (myv < 0 && out[0] && out[0].t == 't') {
          ostr = ostr.substr(1)
          out[0].v = '-' + out[0].v
        }
      }
      jj = ostr.length - 1
      var decpt = out.length
      for (i = 0; i < out.length; ++i)
        if (out[i] != null && out[i].t != 't' && out[i].v.indexOf('.') > -1) {
          decpt = i
          break
        }
      var lasti = out.length
      if (decpt === out.length && ostr.indexOf('E') === -1) {
        for (i = out.length - 1; i >= 0; --i) {
          if (out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue
          if (jj >= out[i].v.length - 1) {
            jj -= out[i].v.length
            out[i].v = ostr.substr(jj + 1, out[i].v.length)
          } else if (jj < 0) out[i].v = ''
          else {
            out[i].v = ostr.substr(0, jj + 1)
            jj = -1
          }
          out[i].t = 't'
          lasti = i
        }
        if (jj >= 0 && lasti < out.length)
          out[lasti].v = ostr.substr(0, jj + 1) + out[lasti].v
      } else if (decpt !== out.length && ostr.indexOf('E') === -1) {
        jj = ostr.indexOf('.') - 1
        for (i = decpt; i >= 0; --i) {
          if (out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue
          j =
            out[i].v.indexOf('.') > -1 && i === decpt
              ? out[i].v.indexOf('.') - 1
              : out[i].v.length - 1
          vv = out[i].v.substr(j + 1)
          for (; j >= 0; --j) {
            if (
              jj >= 0 &&
              (out[i].v.charAt(j) === '0' || out[i].v.charAt(j) === '#')
            )
              vv = ostr.charAt(jj--) + vv
          }
          out[i].v = vv
          out[i].t = 't'
          lasti = i
        }
        if (jj >= 0 && lasti < out.length)
          out[lasti].v = ostr.substr(0, jj + 1) + out[lasti].v
        jj = ostr.indexOf('.') + 1
        for (i = decpt; i < out.length; ++i) {
          if (out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt))
            continue
          j =
            out[i].v.indexOf('.') > -1 && i === decpt
              ? out[i].v.indexOf('.') + 1
              : 0
          vv = out[i].v.substr(0, j)
          for (; j < out[i].v.length; ++j) {
            if (jj < ostr.length) vv += ostr.charAt(jj++)
          }
          out[i].v = vv
          out[i].t = 't'
          lasti = i
        }
      }
    }
    for (i = 0; i < out.length; ++i)
      if (out[i] != null && 'n?'.indexOf(out[i].t) > -1) {
        myv = flen > 1 && v < 0 && i > 0 && out[i - 1].v === '-' ? -v : v
        out[i].v = write_num(out[i].t, out[i].v, myv)
        out[i].t = 't'
      }
    var retval = ''
    for (i = 0; i !== out.length; ++i) if (out[i] != null) retval += out[i].v

    return retval
  }
  SSF._eval = eval_fmt
  var cfregex = /\[[=<>]/
  var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/

  function chkcond(v, rr) {
    if (rr == null) return false
    var thresh = parseFloat(rr[2])
    switch (rr[1]) {
      case '=':
        if (v == thresh) return true
        break
      case '>':
        if (v > thresh) return true
        break
      case '<':
        if (v < thresh) return true
        break
      case '<>':
        if (v != thresh) return true
        break
      case '>=':
        if (v >= thresh) return true
        break
      case '<=':
        if (v <= thresh) return true
        break
    }
    return false
  }

  function choose_fmt(f, v) {
    var fmt = split_fmt(f)
    var l = fmt.length,
      lat = fmt[l - 1].indexOf('@')
    if (l < 4 && lat > -1) --l
    if (fmt.length > 4)
      throw new Error('cannot find right format for |' + fmt.join('|') + '|')
    if (typeof v !== 'number')
      return [4, fmt.length === 4 || lat > -1 ? fmt[fmt.length - 1] : '@']
    switch (fmt.length) {
      case 1:
        fmt =
          lat > -1
            ? ['General', 'General', 'General', fmt[0]]
            : [fmt[0], fmt[0], fmt[0], '@']
        break
      case 2:
        fmt =
          lat > -1
            ? [fmt[0], fmt[0], fmt[0], fmt[1]]
            : [fmt[0], fmt[1], fmt[0], '@']
        break
      case 3:
        fmt =
          lat > -1
            ? [fmt[0], fmt[1], fmt[0], fmt[2]]
            : [fmt[0], fmt[1], fmt[2], '@']
        break
      case 4:
        break
    }
    var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]
    if (fmt[0].indexOf('[') === -1 && fmt[1].indexOf('[') === -1) return [l, ff]
    if (fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
      var m1 = fmt[0].match(cfregex2)
      var m2 = fmt[1].match(cfregex2)
      return chkcond(v, m1)
        ? [l, fmt[0]]
        : chkcond(v, m2)
        ? [l, fmt[1]]
        : [l, fmt[m1 != null && m2 != null ? 2 : 1]]
    }
    return [l, ff]
  }

  function format(fmt, v, o) {
    if (o == null) o = {}
    var sfmt = ''
    switch (typeof fmt) {
      case 'string':
        if (fmt == 'm/d/yy' && o.dateNF) sfmt = o.dateNF
        else sfmt = fmt
        break
      case 'number':
        if (fmt == 14 && o.dateNF) sfmt = o.dateNF
        else sfmt = (o.table != null ? o.table : table_fmt)[fmt]
        if (sfmt == null)
          sfmt =
            (o.table && o.table[default_map[fmt]]) ||
            table_fmt[default_map[fmt]]
        if (sfmt == null) sfmt = default_str[fmt] || 'General'
        break
    }

    //new runze 增加万 亿 格式
    //注："w":2万2500  "w0":2万2500  "w0.0":2万2500.2  "w0.00":2万2500.23......自定义精确度
    var reg = /^(w|W)((0?)|(0\.0+))$/
    if (!!sfmt.match(reg)) {
      if (isNaN(v)) {
        return v
      }

      //var v =300101886.436;
      var acc = sfmt.slice(1) //取得0/0.0/0.00
      var isNegative = false
      if (!isNaN(v) && Number(v) < 0) {
        isNegative = true
        v = Math.abs(v)
      }
      var vInt = parseInt(v)

      var vlength = vInt.toString().length
      if (vlength > 4) {
        if (vlength > 8) {
          var y = parseInt(v / 100000000) //亿
          var w = parseInt(parseFloat(v).subtract(y * 100000000) / 10000) //万
          var q = parseFloat(v).subtract(y * 100000000 + w * 10000) //千以后
          if (acc != '') {
            q = numeral(q).format(acc) //处理精确度
          }
          v = y + '亿' + w + '万' + q
        } else {
          var w = parseInt(v / 10000) //万
          var q = parseFloat(v).subtract(w * 10000) //千以后
          if (acc != '') {
            q = numeral(q).format(acc) //处理精确度
          }
          v = w + '万' + q
        }

        if (v.indexOf('亿0万0') != -1) {
          v = v.replace('0万0', '')
        } else if (v.indexOf('亿0万') != -1) {
          v = v.replace('0万', '')
        } else if (v.indexOf('万0') != -1) {
          v = v.replace('万0', '万')
        }

        //舍弃正则后顾断言写法，旧浏览器不识别（360 V9）
        if (v.indexOf('亿') != -1 && v.indexOf('万') == -1) {
          //1亿/1亿111 => 1亿/1亿0111
          var afterYi = v.substring(v.indexOf('亿') + 1)
          if (afterYi.substring(0, 1) !== '.' && afterYi != '') {
            switch ((parseInt(afterYi) + '').length) {
              case 1:
                afterYi = '000' + afterYi
                break
              case 2:
                afterYi = '00' + afterYi
                break
              case 3:
                afterYi = '0' + afterYi
                break
            }
            v = v.substring(0, v.indexOf('亿') + 1) + afterYi
          }
        } else if (v.indexOf('亿') == -1 && v.indexOf('万') != -1) {
          //3万0011
          var afterWan = v.substring(v.indexOf('万') + 1)
          if (afterWan.substring(0, 1) !== '.' && afterWan != '') {
            switch ((parseInt(afterWan) + '').length) {
              case 1:
                afterWan = '000' + afterWan
                break
              case 2:
                afterWan = '00' + afterWan
                break
              case 3:
                afterWan = '0' + afterWan
                break
            }
            v = v.substring(0, v.indexOf('万') + 1) + afterWan
          }
        } else if (v.indexOf('亿') != -1 && v.indexOf('万') != -1) {
          //1亿0053万0611
          var afterYi = v.substring(v.indexOf('亿') + 1, v.indexOf('万')),
            afterWan = v.substring(v.indexOf('万') + 1)

          switch ((parseInt(afterYi) + '').length) {
            case 1:
              afterYi = '000' + afterYi
              break
            case 2:
              afterYi = '00' + afterYi
              break
            case 3:
              afterYi = '0' + afterYi
              break
          }
          v =
            v.substring(0, v.indexOf('亿') + 1) +
            afterYi +
            v.substring(v.indexOf('万'))

          if (afterWan.substring(0, 1) !== '.' && afterWan != '') {
            switch ((parseInt(afterWan) + '').length) {
              case 1:
                afterWan = '000' + afterWan
                break
              case 2:
                afterWan = '00' + afterWan
                break
              case 3:
                afterWan = '0' + afterWan
                break
            }
            v = v.substring(0, v.indexOf('万') + 1) + afterWan
          }
        }
      } else {
        if (acc != '') {
          v = numeral(v).format(acc) //处理精确度
        }
      }
      if (isNegative) {
        return '-' + v
      } else {
        return v
      }
    }

    if (isgeneral(sfmt, 0)) return general_fmt(v, o)
    if (v instanceof Date) v = datenum_local(v, o.date1904)
    var f = choose_fmt(sfmt, v)
    if (isgeneral(f[1])) return general_fmt(v, o)
    if (v === true) v = 'TRUE'
    else if (v === false) v = 'FALSE'
    else if (v === '' || v == null) return ''
    return eval_fmt(f[1], v, o, f[0])
  }

  function load_entry(fmt, idx) {
    if (typeof idx != 'number') {
      idx = +idx || -1
      for (var i = 0; i < 0x0188; ++i) {
        if (table_fmt[i] == undefined) {
          if (idx < 0) idx = i
          continue
        }
        if (table_fmt[i] == fmt) {
          idx = i
          break
        }
      }
      if (idx < 0) idx = 0x187
    }
    table_fmt[idx] = fmt
    return idx
  }
  SSF.load = load_entry
  SSF._table = table_fmt
  SSF.get_table = function get_table() {
    return table_fmt
  }
  SSF.load_table = function load_table(tbl) {
    for (var i = 0; i != 0x0188; ++i)
      if (tbl[i] !== undefined) load_entry(tbl[i], i)
  }
  SSF.init_table = init_table
  SSF.format = format
}
make_ssf(SSF)

var XLMLFormatMap /*{[string]:string}*/ = {
  'General Number': 'General',
  'General Date': SSF._table[22],
  'Long Date': 'dddd, mmmm dd, yyyy',
  'Medium Date': SSF._table[15],
  'Short Date': SSF._table[14],
  'Long Time': SSF._table[19],
  'Medium Time': SSF._table[18],
  'Short Time': SSF._table[20],
  Currency: '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
  Fixed: SSF._table[2],
  Standard: SSF._table[4],
  Percent: SSF._table[10],
  Scientific: SSF._table[11],
  'Yes/No': '"Yes";"Yes";"No";@',
  'True/False': '"True";"True";"False";@',
  'On/Off': '"Yes";"Yes";"No";@',
}

var unescapexml = (function() {
  /* 22.4.2.4 bstr (Basic String) */
  var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/g,
    coderegex = /_x([\da-fA-F]{4})_/g
  return function unescapexml(text) {
    var s = text + '',
      i = s.indexOf('<![CDATA[')
    if (i == -1)
      return s
        .replace(encregex, function($$, $1) {
          return (
            encodings[$$] ||
            String.fromCharCode(parseInt($1, $$.indexOf('x') > -1 ? 16 : 10)) ||
            $$
          )
        })
        .replace(coderegex, function(m, c) {
          return String.fromCharCode(parseInt(c, 16))
        })
    var j = s.indexOf(']]>')
    return (
      unescapexml(s.slice(0, i)) +
      s.slice(i + 9, j) +
      unescapexml(s.slice(j + 3))
    )
  }
})()

function xlml_format(format, value) {
  var fmt = XLMLFormatMap[format] || unescapexml(format)
  if (fmt === 'General') return SSF._general(value)
  return SSF.format(fmt, value)
}

var basedate = new Date(1899, 11, 31, 0, 0, 0)
var dnthresh = basedate.getTime()
var base1904 = new Date(1900, 2, 1, 0, 0, 0)

function datenum(v, date1904) {
  var epoch = v.getTime()
  if (date1904) epoch -= 1462 * 24 * 60 * 60 * 1000
  return (epoch - dnthresh) / (24 * 60 * 60 * 1000)
}

export function datenum_local(v, date1904) {
  var epoch = Date.UTC(
    v.getFullYear(),
    v.getMonth(),
    v.getDate(),
    v.getHours(),
    v.getMinutes(),
    v.getSeconds()
  )
  var dnthresh_utc = Date.UTC(1899, 11, 31, 0, 0, 0)

  if (date1904) epoch -= 1461 * 24 * 60 * 60 * 1000
  else if (v >= base1904) epoch += 24 * 60 * 60 * 1000
  return (epoch - dnthresh_utc) / (24 * 60 * 60 * 1000)
}

function numdate(v) {
  var out = new Date()
  out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh)
  return out
}
/* ISO 8601 Duration */
function parse_isodur(s) {
  var sec = 0,
    mt = 0,
    time = false
  var m = s.match(
    /P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/
  )
  if (!m) throw new Error('|' + s + '| is not an ISO8601 Duration')
  for (var i = 1; i != m.length; ++i) {
    if (!m[i]) continue
    mt = 1
    if (i > 3) time = true
    switch (m[i].slice(m[i].length - 1)) {
      case 'Y':
        throw new Error(
          'Unsupported ISO Duration Field: ' + m[i].slice(m[i].length - 1)
        )
      case 'D':
        mt *= 24
      /* falls through */
      case 'H':
        mt *= 60
      /* falls through */
      case 'M':
        if (!time) throw new Error('Unsupported ISO Duration Field: M')
        else mt *= 60
      /* falls through */
      case 'S':
        break
    }
    sec += mt * parseInt(m[i], 10)
  }
  return sec
}
var good_pd_date = new Date('2017-02-19T19:06:09.000Z')
if (isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17')
var good_pd = good_pd_date.getFullYear() == 2017
/* parses a date as a local date */
function parseDate(str, fixdate) {
  var d = new Date(str)
  if (good_pd) {
    if (fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000)
    else if (fixdate < 0)
      d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000)
    return d
  }
  if (str instanceof Date) return str
  if (good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
    var s = d.getFullYear()
    if (str.indexOf('' + s) > -1) return d
    d.setFullYear(d.getFullYear() + 100)
    return d
  }
  var n = str.match(/\d+/g) || ['2017', '2', '19', '0', '0', '0']
  var out = new Date(
    +n[0],
    +n[1] - 1,
    +n[2],
    +n[3] || 0,
    +n[4] || 0,
    +n[5] || 0
  )
  if (str.indexOf('Z') > -1)
    out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000)
  return out
}

/* TODO: stress test */
function fuzzynum(s) {
  var v = Number(s)
  if (typeof s == 'number') {
    return s
  }
  if (!isNaN(v)) return v
  var wt = 1
  var ss = s
    .replace(/([\d]),([\d])/g, '$1$2')
    .replace(/[$]/g, '')
    .replace(/[%]/g, function() {
      wt *= 100
      return ''
    })
  if (!isNaN((v = Number(ss)))) return v / wt
  ss = ss.replace(/[(](.*)[)]/, function($$, $1) {
    wt = -wt
    return $1
  })
  if (!isNaN((v = Number(ss)))) return v / wt
  return v
}

function fuzzydate(s) {
  var o = new Date(s),
    n = new Date(NaN)
  var y = o.getYear(),
    m = o.getMonth(),
    d = o.getDate()
  if (isNaN(d)) return n
  if (y < 0 || y > 8099) return n
  if ((m > 0 || d > 1) && y != 101) return o
  if (s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/))
    return o
  if (s.match(/[^-0-9:,\/\\]/)) return n
  return o
}

export function genarate(value) {
  //万 单位格式增加！！！
  var ret = []
  var m = null,
    ct = {},
    v = value

  if (value == null) {
    return null
  }
  if (/^-?[0-9]{1,}[,][0-9]{3}(.[0-9]{1,2})?$/.test(value)) {
    // 表述金额的字符串，如：12,000.00 或者 -12,000.00
    m = value
    v = Number(value.split('.')[0].replace(',', ''))
    let fa = '#,##0'
    if (value.split('.')[1]) {
      fa = '#,##0.'
      for (let i = 0; i < value.split('.')[1].length; i++) {
        fa += 0
      }
    }
    ct = { fa, t: 'n' }
  } else if (value.toString().substr(0, 1) === "'") {
    m = value.toString().substr(1)
    ct = { fa: '@', t: 's' }
  } else if (value.toString().toUpperCase() === 'TRUE') {
    m = 'TRUE'
    ct = { fa: 'General', t: 'b' }
    v = true
  } else if (value.toString().toUpperCase() === 'FALSE') {
    m = 'FALSE'
    ct = { fa: 'General', t: 'b' }
    v = false
  } else if (valueIsError(value)) {
    m = value.toString()
    ct = { fa: 'General', t: 'e' }
  } else if (
    /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(
      value
    )
  ) {
    m = value.toString()
    ct = { fa: '@', t: 's' }
  }
  //  else if (
  //   isRealNum(value) &&
  //   Math.abs(parseFloat(value)) > 0 &&
  //   (Math.abs(parseFloat(value)) >= 1e11 || Math.abs(parseFloat(value)) < 1e-9)
  // ) {
  //   v = numeral(value).value()
  //   var str = v.toExponential()
  //   if (str.indexOf('.') > -1) {
  //     var strlen = str.split('.')[1].split('e')[0].length
  //     if (strlen > 5) {
  //       strlen = 5
  //     }

  //     ct = { fa: '#0.' + new Array(strlen + 1).join('0') + 'E+00', t: 'n' }
  //   } else {
  //     ct = { fa: '#0.E+00', t: 'n' }
  //   }
  //   ct = { fa: 'General', t: 'e' }

  //   m = SSF.format(ct.fa, v)
  // }
  else if (value.toString().indexOf('%') > -1) {
    var index = value.toString().indexOf('%')
    var value2 = value.toString().substr(0, index)
    var value3 = value2.replace(/,/g, '')

    if (index == value.toString().length - 1 && isRealNum(value3)) {
      if (value2.indexOf('.') > -1) {
        if (value2.indexOf('.') == value2.lastIndexOf('.')) {
          var value4 = value2.split('.')[0]
          var value5 = value2.split('.')[1]

          var len = value5.length
          if (len > 9) {
            len = 9
          }

          if (value4.indexOf(',') > -1) {
            var isThousands = true
            var ThousandsArr = value4.split(',')

            for (var i = 1; i < ThousandsArr.length; i++) {
              if (ThousandsArr[i].length < 3) {
                isThousands = false
                break
              }
            }

            if (isThousands) {
              ct = { fa: '#,##0.' + new Array(len + 1).join('0') + '%', t: 'n' }
              v = numeral(value).value()
              m = SSF.format(ct.fa, v)
            } else {
              m = value.toString()
              ct = { fa: '@', t: 's' }
            }
          } else {
            ct = { fa: '0.' + new Array(len + 1).join('0') + '%', t: 'n' }
            v = numeral(value).value()
            m = SSF.format(ct.fa, v)
          }
        } else {
          m = value.toString()
          ct = { fa: '@', t: 's' }
        }
      } else if (value2.indexOf(',') > -1) {
        var isThousands = true
        var ThousandsArr = value2.split(',')

        for (var i = 1; i < ThousandsArr.length; i++) {
          if (ThousandsArr[i].length < 3) {
            isThousands = false
            break
          }
        }

        if (isThousands) {
          ct = { fa: '#,##0%', t: 'n' }
          v = numeral(value).value()
          m = SSF.format(ct.fa, v)
        } else {
          m = value.toString()
          ct = { fa: '@', t: 's' }
        }
      } else {
        ct = { fa: '0%', t: 'n' }
        v = numeral(value).value()
        m = SSF.format(ct.fa, v)
      }
    } else {
      m = value.toString()
      ct = { fa: '@', t: 's' }
    }
  } else if (value.toString().indexOf('.') > -1) {
    if (value.toString().indexOf('.') == value.toString().lastIndexOf('.')) {
      var value1 = value.toString().split('.')[0]
      var value2 = value.toString().split('.')[1]

      var len = value2.length
      if (len > 9) {
        len = 9
      }

      if (value1.indexOf(',') > -1) {
        var isThousands = true
        var ThousandsArr = value1.split(',')

        for (var i = 1; i < ThousandsArr.length; i++) {
          if (!isRealNum(ThousandsArr[i]) || ThousandsArr[i].length < 3) {
            isThousands = false
            break
          }
        }

        if (isThousands) {
          ct = { fa: '#,##0.' + new Array(len + 1).join('0'), t: 'n' }
          v = numeral(value).value()
          m = SSF.format(ct.fa, v)
        } else {
          m = value.toString()
          ct = { fa: '@', t: 's' }
        }
      } else {
        if (isRealNum(value1) && isRealNum(value2)) {
          ct = { fa: '0.' + new Array(len + 1).join('0'), t: 'n' }
          v = numeral(value).value()
          m = SSF.format(ct.fa, v)
        } else {
          m = value.toString()
          ct = { fa: '@', t: 's' }
        }
      }
    } else {
      m = value.toString()
      ct = { fa: '@', t: 's' }
    }
  } else if (isRealNum(value)) {
    m = value.toString()
    v = value.toString()
    ct = { fa: 'General', t: 'n' }
    // v = parseFloat(value)
  } else if (
    isdatetime(value) &&
    (value.toString().indexOf('.') > -1 ||
      value.toString().indexOf(':') > -1 ||
      value.toString().length < 16)
  ) {
    v = datenum_local(parseDate(value.toString().replace(/-/g, '/')))

    if (v.toString().indexOf('.') > -1) {
      if (value.toString().length > 18) {
        ct.fa = 'yyyy-MM-dd hh:mm:ss'
      } else if (value.toString().length > 11) {
        ct.fa = 'yyyy-MM-dd hh:mm'
      } else {
        ct.fa = 'yyyy-MM-dd'
      }
    } else {
      ct.fa = 'yyyy-MM-dd'
    }

    ct.t = 'd'
    m = SSF.format(ct.fa, v)
  } else {
    m = value
    ct.fa = 'General'
    ct.t = 'g'
  }

  return [m, ct, v]
}

export function update(fmt, v) {
  return SSF.format(fmt, v)
}

export function is_date(fmt, v) {
  return SSF.is_date(fmt, v)
}

export function valueShowEs(r, c, d) {
  var value = getcellvalue(r, c, d, 'm')
  if (value == null) {
    value = getcellvalue(r, c, d, 'v')
  } else {
    if (!isNaN(fuzzynum(value))) {
      if (typeof value == 'string' && value.indexOf('%') > -1) {
      } else {
        value = getcellvalue(r, c, d, 'v')
      }
    }
    // else if (!isNaN(parseDate(value).getDate())){
    else if (d[r][c].ct != null && d[r][c].ct.t == 'd') {
    } else if (d[r][c].ct != null && d[r][c].ct.t == 'b') {
    } else {
      value = getcellvalue(r, c, d, 'v')
    }
  }
  return value
}
